{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras_bert import get_base_dict, get_model, compile_model, gen_batch_inputs\n",
    "import codecs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import keras"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_df = pd.read_csv(\"./data/train.csv\")\n",
    "test_df = pd.read_csv(\"./data/test.csv\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>keyword</th>\n",
       "      <th>location</th>\n",
       "      <th>text</th>\n",
       "      <th>target</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Our Deeds are the Reason of this #earthquake M...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Forest fire near La Ronge Sask. Canada</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>5</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>All residents asked to 'shelter in place' are ...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>6</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>13,000 people receive #wildfires evacuation or...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>7</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Just got sent this photo from Ruby #Alaska as ...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7608</th>\n",
       "      <td>10869</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Two giant cranes holding a bridge collapse int...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7609</th>\n",
       "      <td>10870</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>@aria_ahrary @TheTawniest The out of control w...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7610</th>\n",
       "      <td>10871</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>M1.94 [01:04 UTC]?5km S of Volcano Hawaii. htt...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7611</th>\n",
       "      <td>10872</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Police investigating after an e-bike collided ...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7612</th>\n",
       "      <td>10873</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>The Latest: More Homes Razed by Northern Calif...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>7613 rows × 5 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "         id keyword location                                               text  target\n",
       "0         1     NaN      NaN  Our Deeds are the Reason of this #earthquake M...       1\n",
       "1         4     NaN      NaN             Forest fire near La Ronge Sask. Canada       1\n",
       "2         5     NaN      NaN  All residents asked to 'shelter in place' are ...       1\n",
       "3         6     NaN      NaN  13,000 people receive #wildfires evacuation or...       1\n",
       "4         7     NaN      NaN  Just got sent this photo from Ruby #Alaska as ...       1\n",
       "...     ...     ...      ...                                                ...     ...\n",
       "7608  10869     NaN      NaN  Two giant cranes holding a bridge collapse int...       1\n",
       "7609  10870     NaN      NaN  @aria_ahrary @TheTawniest The out of control w...       1\n",
       "7610  10871     NaN      NaN  M1.94 [01:04 UTC]?5km S of Volcano Hawaii. htt...       1\n",
       "7611  10872     NaN      NaN  Police investigating after an e-bike collided ...       1\n",
       "7612  10873     NaN      NaN  The Latest: More Homes Razed by Northern Calif...       1\n",
       "\n",
       "[7613 rows x 5 columns]"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_data = train_df[[\"id\", \"text\", \"target\"]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "pandas.core.series.Series"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(train_data['text'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 166,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "         id                                               text  target\n",
      "0         1  Our Deeds are the Reason of this #earthquake M...       1\n",
      "1         4             Forest fire near La Ronge Sask. Canada       1\n",
      "2         5  All residents asked to 'shelter in place' are ...       1\n",
      "3         6  13,000 people receive #wildfires evacuation or...       1\n",
      "4         7  Just got sent this photo from Ruby #Alaska as ...       1\n",
      "...     ...                                                ...     ...\n",
      "7608  10869  Two giant cranes holding a bridge collapse int...       1\n",
      "7609  10870  @aria_ahrary @TheTawniest The out of control w...       1\n",
      "7610  10871        M1.94 [01:04 UTC]?5km S of Volcano Hawaii.        1\n",
      "7611  10872  Police investigating after an e-bike collided ...       1\n",
      "7612  10873  The Latest: More Homes Razed by Northern Calif...       1\n",
      "\n",
      "[7613 rows x 3 columns]\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "# 将文本中的网址给去除\n",
    "for index, centence in enumerate(train_data['text']):\n",
    "    train_data.loc[index, \"text\"] = re.sub(r\"(http|https)://\\S* ?\", \"\", centence)\n",
    "    \n",
    "print(train_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 195,
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.preprocessing.text import Tokenizer\n",
    "\n",
    "tokenizer = Tokenizer(num_words=10000)\n",
    "tokenizer.fit_on_texts(train_data['text'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 196,
   "metadata": {},
   "outputs": [],
   "source": [
    "one_hot_results = tokenizer.texts_to_sequences(train_df['text'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 197,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "18327"
      ]
     },
     "execution_count": 197,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(tokenizer.word_index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 219,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_train = tokenizer.texts_to_sequences(train_data[\"text\"].values)\n",
    "y_train = train_data[\"target\"].values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 216,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_test = tokenizer.texts_to_sequences(test_df[\"text\"].values)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 240,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential_33\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "embedding_33 (Embedding)     (None, 64, 8)             80000     \n",
      "_________________________________________________________________\n",
      "flatten_33 (Flatten)         (None, 512)               0         \n",
      "_________________________________________________________________\n",
      "dense_35 (Dense)             (None, 1)                 513       \n",
      "=================================================================\n",
      "Total params: 80,513\n",
      "Trainable params: 80,513\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Amber\\Anaconda3\\envs\\dl\\lib\\site-packages\\tensorflow_core\\python\\framework\\indexed_slices.py:433: UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape. This may consume a large amount of memory.\n",
      "  \"Converting sparse IndexedSlices to a dense Tensor of unknown shape. \"\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 6090 samples, validate on 1523 samples\n",
      "Epoch 1/12\n",
      "6090/6090 [==============================] - 1s 91us/step - loss: 0.6768 - acc: 0.5770 - val_loss: 0.6871 - val_acc: 0.5345\n",
      "Epoch 2/12\n",
      "6090/6090 [==============================] - 0s 42us/step - loss: 0.6443 - acc: 0.6097 - val_loss: 0.6568 - val_acc: 0.5509\n",
      "Epoch 3/12\n",
      "6090/6090 [==============================] - 0s 39us/step - loss: 0.5840 - acc: 0.7228 - val_loss: 0.5995 - val_acc: 0.7275\n",
      "Epoch 4/12\n",
      "6090/6090 [==============================] - 0s 38us/step - loss: 0.5125 - acc: 0.8010 - val_loss: 0.5533 - val_acc: 0.7617\n",
      "Epoch 5/12\n",
      "6090/6090 [==============================] - 0s 39us/step - loss: 0.4525 - acc: 0.8284 - val_loss: 0.5214 - val_acc: 0.7676\n",
      "Epoch 6/12\n",
      "6090/6090 [==============================] - 0s 38us/step - loss: 0.4076 - acc: 0.8424 - val_loss: 0.4972 - val_acc: 0.7748\n",
      "Epoch 7/12\n",
      "6090/6090 [==============================] - 0s 39us/step - loss: 0.3723 - acc: 0.8591 - val_loss: 0.4822 - val_acc: 0.7820\n",
      "Epoch 8/12\n",
      "6090/6090 [==============================] - 0s 39us/step - loss: 0.3427 - acc: 0.8681 - val_loss: 0.4738 - val_acc: 0.7859\n",
      "Epoch 9/12\n",
      "6090/6090 [==============================] - 0s 39us/step - loss: 0.3183 - acc: 0.8798 - val_loss: 0.4671 - val_acc: 0.7820\n",
      "Epoch 10/12\n",
      "6090/6090 [==============================] - 0s 38us/step - loss: 0.2963 - acc: 0.8903 - val_loss: 0.4610 - val_acc: 0.7899\n",
      "Epoch 11/12\n",
      "6090/6090 [==============================] - 0s 42us/step - loss: 0.2763 - acc: 0.8985 - val_loss: 0.4596 - val_acc: 0.7866\n",
      "Epoch 12/12\n",
      "6090/6090 [==============================] - 0s 40us/step - loss: 0.2586 - acc: 0.9057 - val_loss: 0.4573 - val_acc: 0.7853\n"
     ]
    }
   ],
   "source": [
    "from keras.datasets import imdb\n",
    "from keras import preprocessing\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Flatten, Dense, Embedding\n",
    "\n",
    "# 特征单词数\n",
    "max_words = 10000\n",
    "# 在20单词后截断文本\n",
    "# 这些单词都属于max_words中的单词\n",
    "maxlen = 64\n",
    "# 嵌入维度\n",
    "embedding_dim = 8\n",
    "\n",
    "# 统计序列长度，将数据集转换成形状为（samples，maxlen）的二维整数张量\n",
    "x_train = preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen)\n",
    "x_test = preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen)\n",
    "\n",
    "# 构建模型\n",
    "model = Sequential()\n",
    "model.add(Embedding(max_words, embedding_dim, input_length=maxlen))\n",
    "# 将3维的嵌入张量展平成形状为（samples，maxlen * embedding_dim）的二维张量\n",
    "model.add(Flatten())\n",
    "model.add(Dense(1, activation='sigmoid'))\n",
    "model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])\n",
    "model.summary()\n",
    "\n",
    "history = model.fit(x_train, y_train, epochs=12, batch_size=64, validation_split=0.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 255,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = model.predict(x_test)\n",
    "a = list(map(lambda data: 1 if data>0.5 else 0, result))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 261,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "merge_dt_dict = {'id':test_df['id'].values,\n",
    "                'target':a}\n",
    "\n",
    "test_result_df = pd.DataFrame(merge_dt_dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 264,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_result_df.to_csv(\"test_result.csv\", index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 232,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x209442f8bc8>"
      ]
     },
     "execution_count": 232,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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4GPg2qjsBmBItHwGMC+qMx5olrDv+cD86HFeTa+1sxdjG7OvvvrK3d03bdrkJ598sk+ZMqXeY9DfSjIhjgukDQ07eTEWd38OeK5K2f8mLE8CJlWz7/1UtvAlg371q1/x2muvsWHDBgYPHsypp54ad0giaRHHBdJc0mDmupGa/fGPf4w7BJGM6NQpdNckK5eaaQoEEcl6uXiBtD4p0YtIndTnNAE5eYG0HqnrRkRqrT6m1q0q0z8qymVq0YtIrdXH1LqSPkr0KTj22GO3+/HTbbfdxo9//OMd7rfHHnsAsHTpUs4444xqj11cXLzD49x2223bTCZ2yimnsHr16lRCF8kIjYJpWJToUzBixAgmTpy4TdnEiRMZMWJESvvvv//+TJqUdPRpSqom+ueee44999yzzscT2Vm5OE1ALlOiT8EZZ5zB3/72t4pfhS5cuJClS5cyYMAA1q5dywknnEDv3r054ogjeOaZZ7bbf+HChXTv3h2A9evXM3z4cAoKChg2bBjr16+vqHfRRRdVTHF83XXXAXDHHXewdOlSjjvuOI477jgA8vPzWb58OQC33nor3bt3p3v37tx2220Vr3fYYYcxevRounXrxsCBA7d5nXLPPvssffv2pVevXpx44ol8/vnnAKxdu5bzzjuPI444goKCAp588kkAXnjhBXr37k2PHj044YQT0vLeSvrU58VRjYJpWBrcxdjLL4eZM9N7zJ49IcqRSe2999706dOHF154gaFDhzJx4kSGDRuGmdG8eXMmT55Mq1atWL58Od/85jcZMmRItZOB3X333bRo0YJZs2Yxa9asipkhAcaOHctee+3Fli1bOOGEE5g1axY/+clPuPXWW3n11Vdp27btNseaPn06DzzwAG+//TbuTt++ffnWt75FmzZtmDdvHhMmTOC+++7jrLPO4sknn+Scc87ZZv8BAwYwdepUzIzx48fz+9//nj/84Q/ceOONtG7dmvfffx+AVatWUVpayujRo3n99dfp0qULK1eurOO7LZlQ3xdHy4957bWhu6ZTp5DkdbE0O6lFn6LE7pvEbht35xe/+AUFBQWceOKJfPrppxUt42Ref/31ioRbUFBAQUFBxbbHH3+c3r1706tXL+bMmcPcuXN3GNObb77J6aefzu67784ee+zBd7/73Yopj7t06VJxs5IjjzyShQsXbrd/SUkJgwYN4ogjjuDmm29mzpw5QJiy+OKLL66o16ZNG6ZOncoxxxxDly5dgDCNsWSPOC6OjhwJCxfC1q3hWUk+ezW4Fv2OWt6ZdNppp3HllVfy7rvvsn79+oqWeFFREaWlpUyfPp0mTZqQn5+fdGriRMla+5988gm33HIL06ZNo02bNowaNarG4/gOpiauOpVxsq6bSy+9lCuvvJIhQ4bw2muvcf3111ccV1MWNyy6OCo7ohZ9ivbYYw+OPfZYzj///G0uwn755Zfss88+NGnShFdffZVFyX6nneCYY46hKOo8nT17NrNmzQLCFMC77747rVu35vPPP+f555+v2Kdly5Z89dVXSY/19NNPs27dOr7++msmT57M0UcfnfI5JU5Z/NBDD1WUDxw4kDvvvLNifdWqVfTr149//etffPLJJwDquskyujgqO6JEXwsjRozgvffeY/jw4RVlI0eOpLi4mMLCQoqKijj00EN3eIyLLrqItWvXUlBQwO9//3v69OkDQI8ePejVqxfdunXj/PPP32Ya4TFjxnDyySdXXIwt17t3b0aNGkWfPn3o27cvF1xwAb169Ur5fK6//nrOPPNMjj766G36/3/5y1+yatUqunfvTo8ePXj11Vdp164d48aN47vf/S49evRg2LBhKb+OZJ4ujsqO2I6+/sehsLDQq44r/+CDDzjssMNiikhqQ3+rbRUV1d8Fy/p8Lck+Zjbd3QuTbWtwffQiDUUcI2GU2CUZdd2IZIimCZBs0WASfbZ1Mcn29DfalkbCSLZoEIm+efPmrFixQokki7k7K1asoHnz5nGHkjU0EkayRUp99GY2GLgdyAPGu/tNVbZ3Ah4C9ozqXO3uz5lZPvAB8GFUdaq7X1jbIDt06EBJSQmlpaW13VXqUfPmzenQoUPcYWSNsWO37aMHjYSReNSY6M0sD7gLOAkoAaaZ2RR3T/zZ5i+Bx939bjM7nHB/2fxo28fu3nNngmzSpEnFLzJFdkZ9jkzRNAGSLVJp0fcB5rv7AgAzmwgMBRITvQOtouXWwNJ0BimSDrpZhjRWqfTRtweWJKyXRGWJrgfOMbMSQmv+0oRtXcxshpn9y8yS/mzTzMaYWbGZFat7RjJFo2CksUol0Seb4KTqVdERwIPu3gE4Bfirme0CLAM6uXsv4ErgUTNrVWVf3H2cuxe6e2G7du1qdwYiKdIoGGmsUkn0JUDHhPUObN8180PgcQB3fwtoDrR1943uviIqnw58DBy8s0GL1IVGwUhjlUqinwZ0NbMuZtYUGA5MqVJnMXACgJkdRkj0pWbWLrqYi5kdAHQFFqQreJHa0Hww0ljVmOjdvQy4BHiRMFTycXefY2Y3mNmQqNpPgdFm9h4wARjlYdD7McCsqHwScKG7a9pDicXIkTBuHHTuDGbhedw4XSyV3NcgJjUTEZEd29GkZg3il7GSu+rzPqcijZVmr5TYxDGuXaQxUoteYqNx7SL1Q4leYqNx7SL1Q4leYqNx7SL1Q4leYqNx7SL1Q4leYqNx7SL1Q6NuJFaa3VEk89SiFxHJcUr0IiI5ToleRCTHKdGLiOQ4JXoRkRynRC8ikuOU6EVEcpwSvYhIjlOiFxHJcSklejMbbGYfmtl8M7s6yfZOZvaqmc0ws1lmdkrCtmui/T40s0HpDF5ERGpW4xQI0c297wJOAkqAaWY2xd3nJlT7JeFesneb2eHAc0B+tDwc6AbsD7xsZge7+5Z0n4iIiCSXSou+DzDf3Re4+yZgIjC0Sh0HWkXLrYGl0fJQYKK7b3T3T4D50fEki+n2fiK5JZVJzdoDSxLWS4C+VepcD/zDzC4FdgdOTNh3apV921d9ATMbA4wB6KTJyGOl2/uJ5J5UWvSWpMyrrI8AHnT3DsApwF/NbJcU98Xdx7l7obsXtmvXLoWQJFN0ez+R3JNKi74E6Jiw3oHKrplyPwQGA7j7W2bWHGib4r6SRXR7P5Hck0qLfhrQ1cy6mFlTwsXVKVXqLAZOADCzw4DmQGlUb7iZNTOzLkBX4J10BS/pp9v7ieSeGhO9u5cBlwAvAh8QRtfMMbMbzGxIVO2nwGgzew+YAIzyYA7wODAXeAG4WCNusptu7yeSe8x9uy7zWBUWFnpxcXHcYTRqRUWhT37x4tCSHztWF2JFsp2ZTXf3wmTbdCtB2Y5u7yeSW5ToRSTrbd0KpaWwbBls2ABbtlQ+ysoytw7QvHnovmzRAnbbLfXlJk3CTe+zgRK9SA7ZtCl0ue2xB+y5Z0hS2WzrVli+HJYuDY9ly5Ivf/55SMD1IS+v8gHhg6UuPdx5ebX7YGjRAg44oPJ3K+mkRC/SgK1dC1OnwhtvhMfUqbB+feX2Zs1Cwk/2aNOm+m3lj2bN6hbX1q2wYkXypJ24/tlnyRN427aw//6w337QvXtY3n9/2HffkBATk3H5Y9dd615WXr5LkuEp7uEDdN268Fi/ftvnmsqSbf/yy3DuVesdeaQSvUijt3w5vPlmZWJ/993QxbDLLtCzZ0gSPXuG5LF69faPVavgk0/C8+rVsHnzjl+vefOaPwzKyrZP4MuWJU/ge+8dkvf++8Phh1cm8/JEXp7MmzbNzPtXF2bhA69Zs/DhmEmZGhujRC+SxRYtqkzqb7wBH3wQyps1g7594eqr4eijoV8/aNVqx8eqyr36D4TqPiSWL4f58yvLypN5mzaVifrQQ7dP3vvtFxJ4tnclxS1TffpK9CJZwj0k8tdfr0zsS6JZplq1gv794Qc/CIm9sLDu3SrlzCr7hvffv27xfv11ZV+0ZC8lepGYbN4MM2ZUJvU33wz92hBav0cfDVddFZ6POKLy4mC2MAsXfSX7KdGL1JN167a9cPrWW5UTyB10EAwZEpL60UfDgQdmz9A8afiU6EUiW7eG0RUbNyZ/rmvZ119DcTFMnx76tM2goAB++MOQ1AcMCH3YIpmiRC85b+1aeP99mDmz8rFs2fYJeUuaZ2FKHK3RvTv87GchsR91VBitIlJflOglp3z22bYJfeZM+OijymFrbdqE4YfHH1+ZhJs23f45WVlt6+blqftFsoMSvTRIW7eGYX4zZmyb1D/7rLJOfn5I6iNGhOdevaBjRyVfaXyU6CXrrV8Ps2dvm9RnzQp93xB+0ditGwwaFBJ6z57Qo0fmf9wi0lAo0UtWWb68MpmXJ/b//je04CGMJ+/ZM1zILE/qhx++82PKRXKZEr3Uq/Kfyy9Zsu1jwYKQ1D/9tLJux44hkX/ve5VJvUsXdb2I1JYSvaTN1q2hj7ykZPtEXv5YtqyydV6uZcvQn37ccdt2vbRtG8tpiOQcJXpJiXvoVqkugS9ZElrjVSey2m230DLv2BFOOqlyufzRoQO0bh3POYk0FiklejMbDNwO5AHj3f2mKtv/CBwXrbYA9nH3PaNtW4D3o22L3X0IktXKyuCOO+C99yqTeElJmJc7UZMmIVF37Bh+9FM1iXfsCHvtpa4WkbjVmOjNLA+4CzgJKAGmmdkUd59bXsfdr0iofynQK+EQ6929Z/pClkwqKwu3EXz88cpkfeSRcNpp2yfxdu2Sz98tItkllRZ9H2C+uy8AMLOJwFBgbjX1RwDXpSc8qU+bN4ck/8QTcPPN4ZecItLwpdIeaw8sSVgvicq2Y2adgS7AKwnFzc2s2Mymmtlp1ew3JqpTXFpammLokk6bN4cfFj3xBPzhD0ryIrkklUSfrIe1uvugDAcmuXvirCGd3L0QOBu4zcwO3O5g7uPcvdDdC9u1a5dCSJJOmzbBsGHw5JPwxz/ClVfGHZGIpFMqib4E6Jiw3gFYWk3d4cCExAJ3Xxo9LwBeY9v+e4lZeZKfPBluvx0uvzzuiEQk3VJJ9NOArmbWxcyaEpL5lKqVzOwQoA3wVkJZGzNrFi23BfpTfd++1LNNm+DMM+Hpp+FPf4Kf/CTuiEQkE2q8GOvuZWZ2CfAiYXjl/e4+x8xuAIrdvTzpjwAmum9ze9vDgHvNbCvhQ+WmxNE6Ep+NG0OSf/ZZuPNOuPjiuCMSkUwxz9Rtx+uosLDQi4uL4w4jp23cGKYV+Pvf4c9/hosuijsiEdlZZjY9uh66Hf0ytpHZsCEk+eeeg3vugR/9KO6IRCTTlOgbkQ0b4PTT4YUXYNw4GD067ohEpD4o0TcS69eHX7e+9BL85S9w/vlxRyQi9UU/YG8AiorC7I677BKei4pqt/+6dTBkiJK8SGOlFn2WKyqCMWNCsgZYtCisQ5iuoCblSf6VV+CBB+DcczMXq4hkJ7Xos9y111Ym+XLr1oXymnz9NZx6akjyDz2kJC/SWKlFn+UWL65debnyJP/66/Dww3DOOemPTUQaBrXos1ynTrUrB1i7Fk45JST5v/5VSV6ksVOiz3Jjx0KLFtuWtWgRypMpT/Jvvhn6988+O/Mxikh2U6LPciNHhjHvnTuHOzV17hzWk12I/eorOPlk+M9/4NFHYfjw+o9XRLKP+ugbgJEjax5hs2ZNSPJvvw0TJoR5bEREQIk+J6xZA4MHw7Rp8NhjYYoDEZFySvQN3JdfhiRfXBzu83r66XFHJCLZRom+AVu9GgYNghkzYNIkGDo07ohEJBsp0TdQq1fDwIEwc2ZI8kOGxB2RiGQrJfoGaNWqkORnzYKnngo/jBIRqY4SfQOzciWcdBLMnh2S/Le/HXdEIpLtUhpHb2aDzexDM5tvZlcn2f5HM5sZPT4ys9UJ2841s3nRQ7Ot7ISVK+HEE2HOnHCfVyV5EUlFjS16M8sD7gJOAkqAaWY2JfHer+5+RUL9S4Fe0fJewHVAIeDA9GjfVWk9i0ZgxYqQ5D/4ICT5wYPjjkhEGopUWvR9gPnuvsDdNwETgR2N7xgBTIiWBwEvufvKKLm/BChF1ZI7DBsG//0vTJmiJC8itZNKom8PLElYL4nKtmNmnYEuwCu12dfMxphZsZkVl5aWphJ3o/Lqq/DPf8LvfhcuwoqI1EYqid6SlHk1dYcDk9x9S232dfdx7l7o7oXt2rVLIaTGwx2uuw7at6+84YiISG2kkuhLgI4J6x2ApdXUHU5lt01t95Uk/vnPMBPlNddA8+ZxRyMiDVEqiX4a0NXMuphZU0Iyn1K1kpkdArQB3koofhEYaGZtzKwNMDAqkxSUt+xgWsEAAA5XSURBVOY7dIALLog7GhFpqGocdePuZWZ2CSFB5wH3u/scM7sBKHb38qQ/Apjo7p6w70ozu5HwYQFwg7uvTO8p5K6XXgpTDv/5z9CsWdzRiEhDZQl5OSsUFhZ6cXFx3GHEzh2OOgo+/RTmzVOiF5EdM7Pp7l6YbJt+GZulXnwRpk6Fe+5RkheRnaM7TGWh8r75zp3hvPPijkZEGjq16LPQ88/DO++EWwY2bRp3NCLS0KlFn2XKW/P5+TBqVNzRiEguUIs+y/z97+FuUePHQ5MmcUcjIrlALfos4g7XXw8HHAA/+EHc0YhIrlCLPos8+yxMnw7336/WvIikj1r0WaK8NX/ggfD978cdjYjkErXos8Qzz4SbfD/4IOyqv4qIpJFa9Flg69bQmu/aFUaOjDsaEck1ajtmgaefhvfeg4cfVmteRNJPLfqYlbfmDz4YRoyIOxoRyUVqP8bsqafg/ffhkUfUmheRzFCLPkZbt8L//R8ceigMHx53NCKSq9SGjNGkSTB7Njz6KOTlxR2NiOQqtehjsmVLaM0fdhicdVbc0YhILlOLPiZPPAFz58LEiWrNi0hmqUUfg/LWfLducOaZcUcjIrkupURvZoPN7EMzm29mV1dT5ywzm2tmc8zs0YTyLWY2M3psd1Pxxuixx+C//w3TEe+ij1oRybAau27MLA+4CzgJKAGmmdkUd5+bUKcrcA3Q391Xmdk+CYdY7+490xx3g7VlC9xwAxxxBHzve3FHIyKNQSp99H2A+e6+AMDMJgJDgbkJdUYDd7n7KgB3/yLdgeaKCRPgww/DiBu15kWkPqSSatoDSxLWS6KyRAcDB5vZv81sqpkNTtjW3MyKo/LTkr2AmY2J6hSXlpbW6gQakrKy0Dffowecfnrc0YhIY5FKi96SlHmS43QFjgU6AG+YWXd3Xw10cvelZnYA8IqZve/uH29zMPdxwDiAwsLCqsfOGUVFMH8+TJ6s1ryI1J9U0k0J0DFhvQOwNEmdZ9x9s7t/AnxISPy4+9LoeQHwGtBrJ2NukMrK4MYboVcvGDo07mhEpDFJJdFPA7qaWRczawoMB6qOnnkaOA7AzNoSunIWmFkbM2uWUN6fbfv2G42//hU+/jhMYGbJviOJiGRIjV037l5mZpcALwJ5wP3uPsfMbgCK3X1KtG2gmc0FtgBXufsKMzsKuNfMthI+VG5KHK3TWGzeHFrzRx4J3/lO3NGISGOT0i9j3f054LkqZf+bsOzAldEjsc5/gCN2PsyG7eGH4ZNP4I471JoXkfqnS4IZtmkT/PrX8I1vwLe/HXc0ItIYaa6bDHvoIVi4EO66S615EYmHWvQZVN6a79sXTj457mhEpLFSiz6DHngAFi+Ge+9Va15E4qMWfYZs3Ahjx8I3vwmDBsUdjYg0ZmrRZ8j998OSJTB+vFrzIhIvtegzYONG+M1v4Kij4KST4o5GRBo7tegzYPx4KCkJffRqzYtI3NSiT7MNG0JrfsAAOOGEuKMREVGLPu3uuw+WLg1z26g1LyLZQC36NFq/Hn77WzjmGDjuuLijEREJ1KJPo3HjYNkyePRRteZFJHuoRZ8m69fDTTfBsceGh4hItlCLPk3uuQc++wweeyzuSEREtqUWfRqsWwe/+x0cf3zonxcRySZK9HVQVAT5+eG+r/n5MHo0fP55uPG3iEi2UddNLRUVwZgxoRUPsGhReHTvHsbOi4hkm5Ra9GY22Mw+NLP5ZnZ1NXXOMrO5ZjbHzB5NKD/XzOZFj3PTFXhcrr22MsknKi2t/1hERFJRY4vezPKAu4CTgBJgmplNSbz3q5l1Ba4B+rv7KjPbJyrfC7gOKAQcmB7tuyr9p1I/Fi9OXv7FF/Ubh4hIqlJp0fcB5rv7AnffBEwEhlapMxq4qzyBu3t52hsEvOTuK6NtLwGD0xN6PDp1ql25iEjcUkn07YElCeslUVmig4GDzezfZjbVzAbXYl/MbIyZFZtZcWmW94GMHQstWmxb1qJFKBcRyUapJPpkv/H0Kuu7Al2BY4ERwHgz2zPFfXH3ce5e6O6F7dq1SyGk+IwcGX4Bu8ceYX3ffcP6yJHxxiUiUp1UEn0J0DFhvQOwNEmdZ9x9s7t/AnxISPyp7NvgrF4Na9fC//xPmPJASV5EslkqiX4a0NXMuphZU2A4MKVKnaeB4wDMrC2hK2cB8CIw0MzamFkbYGBU1mC9/DJcdhl85zthOmIRkWxX46gbdy8zs0sICToPuN/d55jZDUCxu0+hMqHPBbYAV7n7CgAzu5HwYQFwg7uvzMSJ1Id58+DMM+Gww8J4+ry8uCMSEamZuW/XZR6rwsJCLy4ujjuM7axeHW70vWIFvPMOdOkSd0QiIpXMbLq7Fybbpl/GpqCsDIYNgwULQteNkryINCRK9Cn42c/gH/8I94LVpGUi0tDkzKRmVScaKypKz3Hvuw9uvx2uuAJ++MP0HFNEpD7lRIs+2URjY8aE5Z0Z+vivf8GPfwyDB8Pvf7/zcYqIxCEnWvTJJhpbty6U19WCBfC978FBB8HEibBrTnwkikhjlBOJvrqJxqorr8maNWGc/Nat8Oyz0Lp13WMTEYlbTiT6dE40tmULnH02fPQRTJoUWvQiIg1ZTiT6dE40dvXV8Pe/w5/+FG4NKCLS0OVEoi+faKxzZzALz3WZaOzBB+GWW+Dii+HCCzMSqohIvdMvYyP//ndowR99NDz/PDRpUu8hiIjU2Y5+GZsTLfqdtWgRnH56+CbwxBNK8iKSWxp9ol+7FoYMgU2bYMoUaNMm7ohERNKrUY8O37oVvv99mD07dNccemjcEYmIpF+jTvS/+hU8/XSY4mDgwLijERHJjEbbdfPoo+HGIaNHw6WXxh2NiEjmNMpE//bbcP758K1vwZ13hiGZIiK5qtEl+pISOO002H//8MvXpk3jjkhEJLMaVR/9unUwdCh8/XW4gUjbtnFHJCKSeSm16M1ssJl9aGbzzezqJNtHmVmpmc2MHhckbNuSUF71puL1ZutWGDUKZsyACROgW7e4IhERqV81tujNLA+4CzgJKAGmmdkUd59bpepj7n5JkkOsd/eeOx/qzrnxxvBjqJtvhm9/O+5oRETqTyot+j7AfHdf4O6bgInA0MyGlV5PPAHXXx9a9D/9adzRiIjUr1QSfXtgScJ6SVRW1ffMbJaZTTKzjgnlzc2s2MymmtlpyV7AzMZEdYpLS0tTjz4F06fDuefCUUfBPfdohI2IND6pJPpkqbHqTGjPAvnuXgC8DDyUsK1TNNHO2cBtZnbgdgdzH+fuhe5e2K5duxRDr9myZeHia7t2MHkyNGuWtkOLiDQYqST6EiCxhd4BWJpYwd1XuPvGaPU+4MiEbUuj5wXAa0CvnYg3ZevXh2GUq1eHOWz22ac+XlVEJPukkuinAV3NrIuZNQWGA9uMnjGz/RJWhwAfROVtzKxZtNwW6A9UvYibdu5wwQXwzjvwyCPQo0emX1FEJHvVOOrG3cvM7BLgRSAPuN/d55jZDUCxu08BfmJmQ4AyYCUwKtr9MOBeM9tK+FC5KclonbS76aYwxcHYsaFVLyLSmOXcjUeeeSYk97PPDq15XXwVkcag0dx45L33wu0D+/SB8eOV5EVEIIcS/RdfhBuI7LlnmHp4t93ijkhEJDvkTKLfdVcoKAhdN/vtV3N9EZHGImcmNdtrL3j22bijEBHJPjnTohcRkeSU6EVEcpwSvYhIjlOiFxHJcUr0IiI5ToleRCTHKdGLiOQ4JXoRkRyXdZOamVkpsCjuOFLUFlgedxAZlMvnp3NruHL5/Hbm3Dq7e9I7N2Vdom9IzKy4utnickEun5/OreHK5fPL1Lmp60ZEJMcp0YuI5Dgl+p0zLu4AMiyXz0/n1nDl8vll5NzURy8ikuPUohcRyXFK9CIiOU6Jvg7MrKOZvWpmH5jZHDO7LO6Y0s3M8sxshpn9Le5Y0s3M9jSzSWb23+hv2C/umNLFzK6I/k3ONrMJZtY87ph2hpndb2ZfmNnshLK9zOwlM5sXPbeJM8a6qubcbo7+Xc4ys8lmtmc6XkuJvm7KgJ+6+2HAN4GLzezwmGNKt8uAD+IOIkNuB15w90OBHuTIeZpZe+AnQKG7dwfygOHxRrXTHgQGVym7Gvinu3cF/hmtN0QPsv25vQR0d/cC4CPgmnS8kBJ9Hbj7Mnd/N1r+ipAo2scbVfqYWQfg28D4uGNJNzNrBRwD/AXA3Te5++p4o0qrXYHdzGxXoAWwNOZ4doq7vw6srFI8FHgoWn4IOK1eg0qTZOfm7v9w97JodSrQIR2vpUS/k8wsH+gFvB1vJGl1G/A/wNa4A8mAA4BS4IGoa2q8me0ed1Dp4O6fArcAi4FlwJfu/o94o8qI/+fuyyA0uoB9Yo4nU84Hnk/HgZTod4KZ7QE8CVzu7mvijicdzOxU4At3nx53LBmyK9AbuNvdewFf03C/+m8j6qseCnQB9gd2N7Nz4o1K6sLMriV0ERel43hK9HVkZk0ISb7I3Z+KO5406g8MMbOFwETgeDN7JN6Q0qoEKHH38m9gkwiJPxecCHzi7qXuvhl4Cjgq5pgy4XMz2w8gev4i5njSyszOBU4FRnqafuikRF8HZmaEPt4P3P3WuONJJ3e/xt07uHs+4ULeK+6eM61Cd/8MWGJmh0RFJwBzYwwpnRYD3zSzFtG/0RPIkQvNVUwBzo2WzwWeiTGWtDKzwcDPgSHuvi5dx1Wir5v+wPcJrd2Z0eOUuIOSlF0KFJnZLKAn8JuY40mL6FvKJOBd4H3C/+8GPV2AmU0A3gIOMbMSM/shcBNwkpnNA06K1hucas7tTqAl8FKUV+5Jy2tpCgQRkdymFr2ISI5TohcRyXFK9CIiOU6JXkQkxynRi4jkOCV6EZEcp0QvIpLj/j92/GUJuGwTnAAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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Ouooli5dysiRI1m8eHGJ8eXn5zNq1Chmz57N4sWLefvtt3n11VdZuHAhX375JR988AHLli3jqquuAuCBBx5gyZIlLF26lMcee6yc707ZpUxC//TT2OvXrYPrroPVq+EPf4A33oAOHeCXv4SNGys3RpFUV9z/WXHry6tt27acdtppe5eff/55unTpQpcuXVi5cmXMhF6vXj369esHwKmnnsratWtj7vviiy8+YJu5c+cycOBAADp37kyHDh1KjO/999+nd+/eNG3alFq1anH55ZczZ84cjjvuOFatWsXNN9/MzJkzadSoEQAdOnTgiiuuIDc3t0wXBCVKyiT0li1LXn/IITBqFHz4IQwbBk8+CW3bhhOoGhEjEp/S/s8S7ZBDDtl7f/Xq1Tz88MO8+eab5OXl0bdv35jjsAv73QFq1qxJQUFBzH3XqVPngG3KeplMcds3adKEvLw8evTowSOPPML1118PwMyZMxk2bBjz5s0jOzub3btjVkGpMCmT0O+9F+rX339d/fphfbQjjoDHHgvDG/v2DUMcjzsOnngCivm9i0hEvP9nFeHbb7+lYcOGHHrooWzYsIGZM2cm/DV69OjB1KlTAfjggw9ifgOIdvrppzN79mw2b95MQUEBU6ZMoWfPnmzatAl352c/+xmjR49m0aJF7N69m/z8fHr37s3YsWPZtGkT24v2X1WwuC4sqgoKT17feWf4+teyZfgjK+6k9gknwIsvwrvvwm9/G1rt48bBfffBgAGg6yxEDlTW/7NE6tKlC+3bt6djx460adOG7t27J/w1brrpJq666io6depEly5d6Nix497uklhatGjBmDFj6NWrF+7OhRdeyPnnn8+iRYu49tprcXfMjPvvv5+CggIuv/xytm7dyp49e7j99ttp2LBhwo+hJEmbUzQ7O9sra4ILd5g+HW6/PZww7d4dxo6FM86olJcXSaqVK1dy0kknJTuMKqGgoICCggLq1q3L6tWrOffcc1m9ejUZGVWzbRvrd2dmC909O9b2KdPlUh5moVW+bFnoevnwQ/jRj+CSS+Df/052dCJSWbZt20b37t3p3Lkzl1xyCU888USVTeYHo1ok9EIZGWFM7erV4WTp3/8O7dvDjTdqRIxIddC4cWMWLlzI0qVLycvL49xzz012SAlVrRJ6oQYN4K67YM0auP760Go/7jgYM0YjYkQkdVXLhF7oyCNDKYHly+Hcc+H3v4fjjw8XKmlEjIikmmqd0AudeCK89BK8/XYYu3799XDyyfDKK6oRIyKpQwk9yo9+BG+9ta/Y10UXwY9/DAsXJjsyEZHSKaEXYRYS+bJloTzv6tVheOP48Wqti0jVpoRejIyMcPK0Vq1Qc/3WW6Fr11C2V0Ti16tXrwOu+hw/fjy//OUvi31OgwYNAFi/fj2XXnppsfst7VqW8ePH73e15nnnncc3CfwnHjx4MC+++GLC9ldeSujFKCwjmp+/b92CBeEK1Eq6HkokLQwaNIgpU6bst27KlCkMGjSo1Ocec8wx5UqYRRP6jBkzaNy48UHvr6pLnxH1CRarjCjAV1+FvvY//QmGD1cJAUktt9wCiZ6IJysrdEkW59JLL2XUqFF8//331KlTh7Vr17J+/XqysrLo06cPX3/9Nbt27eKee+5hwIAB+z137dq1XHDBBSxbtowdO3ZwzTXXsGLFCk466SR27Nixd7sbbriB+fPns2PHDi699FJGjx7NI488wvr16znrrLNo2rQps2fPJjMzkwULFtC0aVMeeuihvaV3hwwZwi233MLatWvp168fPXr04J133qF58+a88sor1KtXr9T3YdasWfzmN7+hoKCA0047jYkTJ1KnTh1GjhzJ9OnTycjI4Nxzz+XBBx/kb3/7G6NHj6ZmzZo0atSIOXPmHNybX4QSejGKKxe6e3co+jViBMyZA089BSWUghCp9po0aULXrl15/fXXGTBgAFOmTOHnP/859erVY9q0aRx66KF8+eWXnH766fTv37/YyZEnTpxI/fr1ycvLIy8vjy5duux97N577+Xwww9n9+7d9OnTh7y8PEaMGMFDDz3E7Nmzadq06X77WrhwIZMnT+b999/H3enWrRs9e/bksMMOY/Xq1Tz//PM8+eSTXHbZZbz00kulTlaxc+dOBg8ezKxZszjhhBO46qqrmDhxIldddRXTpk3jX//6F2a2t7tnzJgxzJw5k+bNmye0C0gJvRgtW+6bHSlaq1ahLsyf/gS/+x0sXgxTp0LU35ZIlVVSS7oiFXa7FCb0p59+GnfnjjvuYM6cOdSoUYPPPvuMjRs3ctRRR8Xcx5w5cxgxYgQAnTp1olOnTnsfmzp1KpMmTaKgoIANGzawYsWK/R4vau7cufz0pz/dW7734osv5q233qJ///60bt2arKwsoOR669FWrVpF69atOeGEEwC4+uqrmTBhAsOHD6du3boMGTKE888/nwsuuACA7t27M3jwYC677LK9ddsTQX3oxSipjGiNGnDbbfDPf4ap8M44A/78Z42CESnORRddxKxZs1i0aBE7duygS5cu5ObmsmnTJhYuXMiSJUs48sgjY9Y/jxar9f7xxx/z4IMPMmvWLPLy8jj//PNL3U9JRQkL66hDyfXW49lfRkYG8+bN45JLLuHll1+mb9++ADz++OPcc889rFu3jqysLDZv3lzqa8RDCb0YOTnhitFWrUI/eatWYTm6jGj37qGF3qdPqAczaBB8+23yYhapqho0aECvXr34xS9+sfdk6JYtWzjiiCOoVasWs2fP5pNYX4mj/PjHPyY3MrnpsmXLyMvLA0Id9UMOOYRGjRqxceNGXnvttb3PadiwIVu3bo25r5dffpnt27fz3XffMW3aNM4888yDPr527dqxdu1a1qxZA8AzzzxDz5492bZtG1u2bOG8885j/Pjxe+cv/fDDD+nWrRtjxoyhadOmrFu37qBfO5q6XEqQk1N6HeimTeHVV+GBB8KMSYsWhS6YyDc2EYkYNGgQF1988d4RLzk5OVx44YVkZ2eTlZVFu3btSnz+DTfcwDXXXEOnTp3Iysqia9euQJhK7pRTTqFDhw4H1FEfOnQo/fr14+ijj2b27Nl713fp0oXBgwfv3ceQIUM45ZRT4upeiaVu3bpMnjyZn/3sZ3tPig4bNoyvvvqKAQMGsHPnTtydcePGAXDbbbexevVq3J0+ffrQuXPng3rdoqpFPfTK8tZbMHAgbN4MDz8chj1qFIwkm+qhpy7VQ0+iM88MQ8J69QozJOXkQIxveyIiFUIJPcGaNYMZM+Cee+CFFyA7GyJdfSKSom688UaysrL2u02ePDnZYR1AfegVoEaNcGFSjx7hRGm3bvDoo3DtteqCkeQonPtSDs6ECRMq/TUPpjtcLfQK1LNnGAXTowdcdx1cdZUm0JDKV7duXTZv3nxQCUKSw93ZvHkzdevWLdPz1EKvYEceCa+/Hsav3313qAPzt79Bx47JjkyqixYtWpCfn8+mTZuSHYqUQd26dWnRokWZnqNRLpXozTfh8svDWPU//xkGD052RCKSajTKpYro3TuMgjn9dLjmmpDQv/su2VGJSLpQQq9kRx0Fb7wRJqn+r/8KNdZXrEh2VCKSDpTQk6BmTRg9Gv7+d/jySzjtNHjmmWRHJSKpTgk9ic4+O4yCOe20MALm2mtj12AXEYmHEnqSHXMM/OMfYdz65MlhzLq6YETkYMSV0M2sr5mtMrM1ZjaymG0uM7MVZrbczJ5LbJjpLSMjXFn62muwcSOceio89pjK8YpI2ZSa0M2sJjAB6Ae0BwaZWfsi2xwP/A7o7u4dgFsqINa095OfwAcfhNEwN90E550HGzYkOyoRSRXxtNC7Amvc/SN3/wGYAgwoss11wAR3/xrA3b9IbJjVx5FHhnK8f/5zmEDj5JNh2rRkRyUiqSCehN4ciK6+nh9ZF+0E4AQze9vM3jOzvrF2ZGZDzWyBmS3QVWvFM4Mbbgi11Vu1gosvhiFDVDZAREoWT0KPVdGnaO9uBnA80AsYBDxlZo0PeJL7JHfPdvfsZs2alTXWaqddO3j3XbjjDnj66TBpxnvvJTsqEamq4kno+cCxUcstgPUxtnnF3Xe5+8fAKkKCl3KqXTvUgfnnP6GgIBT6Gj063BcRiRZPQp8PHG9mrc2sNjAQmF5km5eBswDMrCmhC+ajRAZa3Z15JixdGmrB3H13SOyR6QtFRIA4Erq7FwDDgZnASmCquy83szFm1j+y2Uxgs5mtAGYDt7l7Yqaxlr0aNQrlAqZMgVWrQhfMX/6i4Y0iEsQ1Dt3dZ7j7Ce7e1t3vjay7y92nR+67u//K3du7+8nuPqUig05XubmQmRkmyMjMDMux/PznYXhjt27hZOkll4QSAiJSvelK0SoiNzdMKv3JJ6HF/cknYbm4pN6iRSjy9eCD8L//G4Y3zpxZuTGLSNWihF5F3HnngXVctm8P64tTowb8+tcwbx40aQJ9+8KIEbBjR8XGKiJVkxJ6FfHpp2VbH61z5zAT0i23hLlLTz011F0XkepFCb2KaNmybOuLqlsXxo0LJXm3bAl11seOhd27ExejiFRtSuhVxL33Qv36+6+rXz+sL4tzzoG8POjfH37721CiN55WvoikPiX0KiInByZNCpf6m4WfkyaF9WXVpEmYiHry5NAV06kTPP984mMWkapFk0SnuY8+giuvhHfeCRclTZgAjQ8oyiAiqUKTRFdjbdqEsgF/+AO88EI4gfrPfyY7KhGpCEro1UBGBowaFVrpderAWWfByJHwww/JjkxEEkkJvRrp2jWU5L3uOrj/fk13J5JulNCrmQYN4Ikn4JVXID8/1IO58Ub47LNkRyYi5aWEXk317w/LlsEvfhFG07RtCzffrCnvRFKZEno1duSR8PjjsHo1XHFFGAHTpk0oJ7BxY7KjE5GyUkIXMjPhqadCSd6BA2H8+JDYb79dVRxFUokSuuzVtm24GGnlyjCP6dixIdnfcQdsVnV7kSpPCV0OcMIJ8MwzsHw5XHgh3HcftG4Nd90FX3+d7OhEpDhK6FKsk04KJQPy8uAnPwkXJ7VuDWPGhAJgIlK1KKFLqTp2DLVhliwJFyX9/vchsf/Hf8DWrcmOTkQKKaFL3Dp3hmnTYOHCMEn1nXeGxH7//bBtW7KjExEldCmzLl1g+vQwU1LXrqGMQJs28Kc/HTjrkohUHiV0OWinnQYzZoQaMVlZ8JvfhMT+8MOaBk8kGZTQpdzOOCPMlPTWW9ChQ5gK77jjwoVK33+f7OhEqg8ldEmYHj1g1iyYPTuMaR8+PCT2xx9XZUeRyqCELgnXq1eouf6Pf4Q5UW+4IYxtf+op2LUr2dGJpC8ldKkQZtCnD8ydC6+/HurGXHcdHHts6JKZPx+SNFmWSNpSQpcKZRYuSnrvvXACtXt3mDgxjI5p1w5Gj4Y1a5IdpUh6UEKXSmEG/frBSy/B55/Dk0/CMceEhH788XD66fDoo/DFF8mOVCR1KaFLpTvsMBgyJJw8/fRTeOAB2LkTRowISb5fP3j2WV2sJFJWSuiSVC1awG23hbICH3wQ7q9YAVdeGfrdc3JCV41OpoqUTgldqoyOHeGPf4SPP4Y5c0JSf+01OP/80HIfPhzefVcnU0WKo4ReTeXmhlrnNWqEn7m5yY5onxo14Mwzw/j1zz+Hl18ORcH+8hf40Y/C2Pa77goTcojIPkro1VBuLgwdCp98Elq7n3wSlqtSUi9UuzYMGABTp4Zp8SZPDgXB7rknjJLJzoZx4zQXqgiAeZK+v2ZnZ/uCBQuS8trVXWZmSOJFtWoFa9dWdjQHZ/16mDIlfAgtWhRa9X36hD73n/4UDj002RGKVAwzW+ju2TEfU0KvfmrUiN0PbQZ79lR+POW1ciU891xI7h9/DHXrQv/+Ibn37g0NGiQ7QpHEUUKX/aRDCz0W93DSNDcXXnghzINas2aoBNm9+75b8+bJjlTk4Cmhy34K+9Cja5fXrw+TJoVWbTrYtSuMc58zB95+G95/f19J31atQiGxwgTfoUNI/CKpQAldDpCbG2Yc+vTTUEDr3nvTJ5nHsmsXLF4cknvh7fPPw2OHHhpKABcm+a5d4ZBDkhuvSHHKndDNrC/wMFATeMrd7yvy+GBgLPBZZNVj7v5USftUQpdkcg/97XPn7kvwy5eHx2rWhFNO2b+b5phjkhuvSKFyJXQzqwn8GzgHyAfmA4PcfUXUNoOBbHcfHm9QSuhS1Xz9deiDL0zy8+aFkgQQhkpGJ/gOHcLJZZHKVlJCz4jj+V2BNe7+UWRnU4ABwIoSnyWSYg47DM47L9wgTMpR2E0zd26YlenZZ8NjjRuHbprCBN+1azgPIZJM8ST05sC6qOV8oFuM7S4xsx8TWvO3uvu6ohuY2VBgKEDLli3LHq1IJapdG7p1C7df/Sp003z44b4umrlzQ2kCgIwMOPnkUDmyTZswY1ObNuHWokV4XKSixdPl8jPgJ+4+JLJ8JdDV3W+K2qYJsM3dvzezYcBl7t67pP2qy0XSwebNoZvm7bdh4cLQL792LRQU7NsmIyOMrClM8NG3tm2hUaOkhS8pqLxdLvnAsVHLLYD10Ru4++aoxSeB+8sapEgqatIELrgg3AoVFEB+Pnz00YG3F18MHwLRDj88drJv0ybM8KTWvcQrnj+V+cDxZtaaMIplIHB59AZmdrS7F1bT6A+sTGiUIikkIyNcvJWZGa5ULWrLltCSL5rsFy+GadP2LxVcs+aBrfvo7pzGjSvrqCQVlJrQ3b3AzIYDMwnDFp929+VmNgZY4O7TgRFm1h8oAL4CBldgzCIprVGjcPVqVtaBj+3eDZ99Frt1/9//DV9+uf/2TZuG6pOxbocfHso5SPWhC4tEUsi334bW/YcfhiS/Zs2+26ef7l+jp3Hj4pP9EUco2aeq8vahi0gVceih0LlzuBX1/fch2Ucn+TVrYP58+NvfQuu/UIMGxSf7o4/WGPtUpYQukibq1Ak14tu1O/CxXbtCQbboRL96NeTlwSuv7N9vX6/egUm+bdtwArhhw/Ch0rBheD218qsWJXSRaqBWrX3JuaiCAli37sCW/apVYT7X778vfp/RCT76frw/C+/rwyExlNBFqrmMjFDaoHVrOOec/R/bs2ffSdqvvw59+Fu37vsZff/bb+Grr8I4/MLlbdvimwM2I+PAZF+vXrj6tujPWOvi2bZWrfT/0FBCF5Fi1agRxsIfe2zp28ayZw98992BiT/Wh0HRx3bsCB8QO3aEUs/bt++7fzBjOWrUKD75164dkr1Z2K7wfmnLZdk2evmKK6BXr4N7T0uihC4iFaZGjX1dK4mqWOke6uxEJ/jo+0V/lvbY9u3hHIL7vtuePfEvl2XbwuWePRPzXhSlhC4iKcUs9LnXqRMKqsk+GpwkIpImlNBFRNKEErqISJpQQhcRSRNK6FIpcnND9cEaNcLP3NxkRySSfjTKRSpcbi4MHRqGh0G4BH3o0HA/Jyd5cYmkG7XQpcLdeee+ZF5o+/awXkQSR4ZQOyQAAAiUSURBVAldKtynn5ZtvYgcHCV0qXDFzQeuecJFEksJXSrcvfeGmhnR6tcP60UkcZTQpcLl5MCkSWFuTLPwc9IknRAVSTSNcpFKkZOjBC5S0dRCFxFJE0roIiJpQgldRCRNKKGLiKQJJXQRkTShhC4ikiaU0EVE0oQSuohImlBCFxFJE0roIiJpQgldRCRNKKGLiKQJJXQRkTShhC5pSZNSS3Wk8rmSdjQptVRXaqFL2tGk1FJdKaFL2tGk1FJdxZXQzayvma0yszVmNrKE7S41Mzez7MSFKFI2mpRaqqtSE7qZ1QQmAP2A9sAgM2sfY7uGwAjg/UQHKVIWmpRaqqt4WuhdgTXu/pG7/wBMAQbE2O4PwAPAzgTGJ1JmmpRaqqt4EnpzYF3Ucn5k3V5mdgpwrLu/WtKOzGyomS0wswWbNm0qc7Ai8crJgbVrYc+e8FPJXKqDeBK6xVjnex80qwGMA35d2o7cfZK7Z7t7drNmzeKPUkREShVPQs8Hjo1abgGsj1puCHQE/s/M1gKnA9N1YlREpHLFk9DnA8ebWWszqw0MBKYXPujuW9y9qbtnunsm8B7Q390XVEjEIiISU6kJ3d0LgOHATGAlMNXdl5vZGDPrX9EBiohIfOK69N/dZwAziqy7q5hte5U/LBERKStdKSoikiaU0EVE0oQSuohImlBCFxFJE0roIuWkyTSkqtAEFyLloMk0pCpRC12kHDSZhlQlSugi5aDJNKQqUUIXKQdNpiFViRK6SDloMg2pSpTQRcpBk2lIVaJRLiLllJOjBC5Vg1roIiJpQgldRCRNKKGLiKQJJXQRkTShhC4ikiaU0EVE0oQSukiKUXVHKY7GoYukEFV3lJKohS6SQlTdUUqihC6SQlTdUUqihC6SQlTdUUqihC6SQlTdUUqihC6SQlTdUUqiUS4iKUbVHaU4aqGLiKQJJXQRkTShhC4ikiaU0EVE0oQSuoiUSLVjUodGuYhIsVQ7JrWohS4ixVLtmNSihC4ixVLtmNSihC4ixVLtmNSihC4ixVLtmNSihC4ixVLtmNQSV0I3s75mtsrM1pjZyBiPDzOzD8xsiZnNNbP2iQ9VRJIhJwfWroU9e8JPJfOqq9SEbmY1gQlAP6A9MChGwn7O3U929yzgAeChhEcqIiIliqeF3hVY4+4fufsPwBRgQPQG7v5t1OIhgCcuRBERiUc8FxY1B9ZFLecD3YpuZGY3Ar8CagO9Y+3IzIYCQwFa6jS5iEhCxdNCtxjrDmiBu/sEd28L3A6MirUjd5/k7tnunt2sWbOyRSoiaU9lBsonnhZ6PnBs1HILYH0J208BJpYnKBGpflRmoPziaaHPB443s9ZmVhsYCEyP3sDMjo9aPB9YnbgQRaQ6UJmB8iu1he7uBWY2HJgJ1ASedvflZjYGWODu04HhZnY2sAv4Gri6IoMWkfSjMgPlF1e1RXefAcwosu6uqPs3JzguEalmWrYM3Syx1kt8dKWoiFQJKjNQfkroIlIlqMxA+WmCCxGpMnJylMDLQy10EZE0oYQuItVWul3IpC4XEamW0vFCJrXQRaRaSscLmZTQRaRaSscLmZTQRaRaSsf5UpXQRaRaSscLmZTQRaRaSscLmTTKRUSqrXS7kEktdBGRNKGELiJSSSr6QiZ1uYiIVILKuJBJLXQRkUpQGRcyKaGLiFSCyriQSQldRKQSVMaFTEroIiKVoDIuZFJCFxGpBJVxIZNGuYiIVJKKvpBJLXQRkTShhC4ikiaU0EVE0oQSuohImlBCFxFJE+buyXlhs03AJ0l58bJrCnyZ7CAqSDofG6T38enYUld5jq+VuzeL9UDSEnoqMbMF7p6d7DgqQjofG6T38enYUldFHZ+6XERE0oQSuohImlBCj8+kZAdQgdL52CC9j0/Hlroq5PjUhy4ikibUQhcRSRNK6CIiaUIJvQRmdqyZzTazlWa23MxuTnZMiWZmNc1ssZm9muxYEsnMGpvZi2b2r8jv74xkx5QoZnZr5O9xmZk9b2Z1kx1TeZjZ02b2hZkti1p3uJm9YWarIz8PS2aMB6uYYxsb+bvMM7NpZtY4Ua+nhF6yAuDX7n4ScDpwo5m1T3JMiXYzsDLZQVSAh4HX3b0d0Jk0OUYzaw6MALLdvSNQExiY3KjK7a9A3yLrRgKz3P14YFZkORX9lQOP7Q2go7t3Av4N/C5RL6aEXgJ33+DuiyL3txKSQvPkRpU4ZtYCOB94KtmxJJKZHQr8GPgLgLv/4O7fJDeqhMoA6plZBlAfWJ/keMrF3ecAXxVZPQD4z8j9/wQuqtSgEiTWsbn73929ILL4HtAiUa+nhB4nM8sETgHeT24kCTUe+C2wJ9mBJFgbYBMwOdKd9JSZHZLsoBLB3T8DHgQ+BTYAW9z978mNqkIc6e4bIDSsgCOSHE9F+QXwWqJ2poQeBzNrALwE3OLu3yY7nkQwswuAL9x9YbJjqQAZQBdgorufAnxH6n5l30+kL3kA0Bo4BjjEzK5IblRyMMzsTkK3bm6i9qmEXgozq0VI5rnu/t/JjieBugP9zWwtMAXobWbPJjekhMkH8t298NvUi4QEnw7OBj52903uvgv4b+BHSY6pImw0s6MBIj+/SHI8CWVmVwMXADmewIuBlNBLYGZG6Idd6e4PJTueRHL337l7C3fPJJxUe9Pd06Kl5+6fA+vM7MTIqj7AiiSGlEifAqebWf3I32cf0uSEbxHTgasj968GXkliLAllZn2B24H+7r49kftWQi9Zd+BKQut1SeR2XrKDkrjcBOSaWR6QBfxHkuNJiMi3jheBRcAHhP/hlL5M3syeB94FTjSzfDO7FrgPOMfMVgPnRJZTTjHH9hjQEHgjklMeT9jr6dJ/EZH0oBa6iEiaUEIXEUkTSugiImlCCV1EJE0ooYuIpAkldBGRNKGELiKSJv4/giihzdACu7YAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "acc = history.history['acc']\n",
    "val_acc = history.history['val_acc']\n",
    "loss = history.history['loss']\n",
    "val_loss = history.history['val_loss']\n",
    "\n",
    "epochs = range(1, len(history.history['acc']) + 1)\n",
    "\n",
    "plt.plot(epochs, acc, 'bo', label='Trainning acc')\n",
    "plt.plot(epochs, val_acc, 'b', label='Validation acc')\n",
    "plt.title('Training and validation accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.figure()\n",
    "\n",
    "plt.plot(epochs, loss, 'bo', label='Training loss')\n",
    "plt.plot(epochs, val_loss, 'b', label='Validation_loss')\n",
    "plt.title('Training and validation loss')\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### word2vec "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 236,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.20157221  0.3416196  -0.2405194   0.24683097  0.40844762  0.14912279\n",
      "  0.81273454  0.03109349]\n"
     ]
    }
   ],
   "source": [
    "from gensim.models import Word2Vec\n",
    "import re\n",
    "sentences = []\n",
    "\n",
    "stop = '[’!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~]+'\n",
    "for sentence in train_data['text']:\n",
    "    sentence = re.sub(stop, '', sentence)\n",
    "    sentences.append(sentence.split())\n",
    "    \n",
    "# size嵌入的维度，window窗口大小，workers训练线程数\n",
    "# 忽略单词出现频率小于min_count的单词\n",
    "# sg=1使用Skip-Gram，否则使用CBOW\n",
    "\n",
    "model = Word2Vec(sentences, size=8, window=1, min_count=1, workers=4, sg=1)\n",
    "print(model.wv['Forest'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 239,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 6090 samples, validate on 1523 samples\n",
      "Epoch 1/50\n",
      "6090/6090 [==============================] - 0s 78us/step - loss: 0.7274 - accuracy: 0.5542 - val_loss: 0.6837 - val_accuracy: 0.5620\n",
      "Epoch 2/50\n",
      "6090/6090 [==============================] - 0s 27us/step - loss: 0.6787 - accuracy: 0.5773 - val_loss: 0.6686 - val_accuracy: 0.6001\n",
      "Epoch 3/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6778 - accuracy: 0.5793 - val_loss: 0.6635 - val_accuracy: 0.6198\n",
      "Epoch 4/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6722 - accuracy: 0.5977 - val_loss: 0.6616 - val_accuracy: 0.6211\n",
      "Epoch 5/50\n",
      "6090/6090 [==============================] - 0s 25us/step - loss: 0.6692 - accuracy: 0.5992 - val_loss: 0.6580 - val_accuracy: 0.6277\n",
      "Epoch 6/50\n",
      "6090/6090 [==============================] - 0s 25us/step - loss: 0.6663 - accuracy: 0.6028 - val_loss: 0.6701 - val_accuracy: 0.5890\n",
      "Epoch 7/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6692 - accuracy: 0.6018 - val_loss: 0.6575 - val_accuracy: 0.6264\n",
      "Epoch 8/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6686 - accuracy: 0.5897 - val_loss: 0.6593 - val_accuracy: 0.6277\n",
      "Epoch 9/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6693 - accuracy: 0.5987 - val_loss: 0.6634 - val_accuracy: 0.6244\n",
      "Epoch 10/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6693 - accuracy: 0.6000 - val_loss: 0.6676 - val_accuracy: 0.6146\n",
      "Epoch 11/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6677 - accuracy: 0.6007 - val_loss: 0.6672 - val_accuracy: 0.5929\n",
      "Epoch 12/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6700 - accuracy: 0.5954 - val_loss: 0.6605 - val_accuracy: 0.6244\n",
      "Epoch 13/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6661 - accuracy: 0.6020 - val_loss: 0.6575 - val_accuracy: 0.6316\n",
      "Epoch 14/50\n",
      "6090/6090 [==============================] - 0s 25us/step - loss: 0.6689 - accuracy: 0.5974 - val_loss: 0.6616 - val_accuracy: 0.6106\n",
      "Epoch 15/50\n",
      "6090/6090 [==============================] - 0s 25us/step - loss: 0.6695 - accuracy: 0.5962 - val_loss: 0.6605 - val_accuracy: 0.6080\n",
      "Epoch 16/50\n",
      "6090/6090 [==============================] - 0s 27us/step - loss: 0.6651 - accuracy: 0.6028 - val_loss: 0.6591 - val_accuracy: 0.6303\n",
      "Epoch 17/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6697 - accuracy: 0.5915 - val_loss: 0.6622 - val_accuracy: 0.6218\n",
      "Epoch 18/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6676 - accuracy: 0.5979 - val_loss: 0.6618 - val_accuracy: 0.6080\n",
      "Epoch 19/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6662 - accuracy: 0.6002 - val_loss: 0.6598 - val_accuracy: 0.6067\n",
      "Epoch 20/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6717 - accuracy: 0.5924 - val_loss: 0.6700 - val_accuracy: 0.6139\n",
      "Epoch 21/50\n",
      "6090/6090 [==============================] - 0s 27us/step - loss: 0.6683 - accuracy: 0.5954 - val_loss: 0.6591 - val_accuracy: 0.6093\n",
      "Epoch 22/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6650 - accuracy: 0.5997 - val_loss: 0.6598 - val_accuracy: 0.6297\n",
      "Epoch 23/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6684 - accuracy: 0.5946 - val_loss: 0.6596 - val_accuracy: 0.6330\n",
      "Epoch 24/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6682 - accuracy: 0.6010 - val_loss: 0.6609 - val_accuracy: 0.6100\n",
      "Epoch 25/50\n",
      "6090/6090 [==============================] - 0s 25us/step - loss: 0.6643 - accuracy: 0.6080 - val_loss: 0.6575 - val_accuracy: 0.6336\n",
      "Epoch 26/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6686 - accuracy: 0.5969 - val_loss: 0.6575 - val_accuracy: 0.6349\n",
      "Epoch 27/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6683 - accuracy: 0.6039 - val_loss: 0.6573 - val_accuracy: 0.6336\n",
      "Epoch 28/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6668 - accuracy: 0.6016 - val_loss: 0.7020 - val_accuracy: 0.5850\n",
      "Epoch 29/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6672 - accuracy: 0.6041 - val_loss: 0.6756 - val_accuracy: 0.6093\n",
      "Epoch 30/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6677 - accuracy: 0.5966 - val_loss: 0.6570 - val_accuracy: 0.6349\n",
      "Epoch 31/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6688 - accuracy: 0.5951 - val_loss: 0.6634 - val_accuracy: 0.6244\n",
      "Epoch 32/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6702 - accuracy: 0.5967 - val_loss: 0.6569 - val_accuracy: 0.6330\n",
      "Epoch 33/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6777 - accuracy: 0.5829 - val_loss: 0.6769 - val_accuracy: 0.6067\n",
      "Epoch 34/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6647 - accuracy: 0.6064 - val_loss: 0.6571 - val_accuracy: 0.6369\n",
      "Epoch 35/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6642 - accuracy: 0.6021 - val_loss: 0.6614 - val_accuracy: 0.6264\n",
      "Epoch 36/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6634 - accuracy: 0.6113 - val_loss: 0.6578 - val_accuracy: 0.6389\n",
      "Epoch 37/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6642 - accuracy: 0.6046 - val_loss: 0.6702 - val_accuracy: 0.5772\n",
      "Epoch 38/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6636 - accuracy: 0.6015 - val_loss: 0.6571 - val_accuracy: 0.6271\n",
      "Epoch 39/50\n",
      "6090/6090 [==============================] - 0s 27us/step - loss: 0.6773 - accuracy: 0.5860 - val_loss: 0.6729 - val_accuracy: 0.5739\n",
      "Epoch 40/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6656 - accuracy: 0.6030 - val_loss: 0.6596 - val_accuracy: 0.6100\n",
      "Epoch 41/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6651 - accuracy: 0.6023 - val_loss: 0.6740 - val_accuracy: 0.5673\n",
      "Epoch 42/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6643 - accuracy: 0.6031 - val_loss: 0.6569 - val_accuracy: 0.6244\n",
      "Epoch 43/50\n",
      "6090/6090 [==============================] - 0s 28us/step - loss: 0.6638 - accuracy: 0.6057 - val_loss: 0.6565 - val_accuracy: 0.6271\n",
      "Epoch 44/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6605 - accuracy: 0.6115 - val_loss: 0.6581 - val_accuracy: 0.6356\n",
      "Epoch 45/50\n",
      "6090/6090 [==============================] - 0s 25us/step - loss: 0.6690 - accuracy: 0.5903 - val_loss: 0.6564 - val_accuracy: 0.6389\n",
      "Epoch 46/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6638 - accuracy: 0.6041 - val_loss: 0.6623 - val_accuracy: 0.6093\n",
      "Epoch 47/50\n",
      "6090/6090 [==============================] - 0s 25us/step - loss: 0.6684 - accuracy: 0.6069 - val_loss: 0.6792 - val_accuracy: 0.6067\n",
      "Epoch 48/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6655 - accuracy: 0.6074 - val_loss: 0.6563 - val_accuracy: 0.6330\n",
      "Epoch 49/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6673 - accuracy: 0.5954 - val_loss: 0.6568 - val_accuracy: 0.6277\n",
      "Epoch 50/50\n",
      "6090/6090 [==============================] - 0s 26us/step - loss: 0.6637 - accuracy: 0.6053 - val_loss: 0.6655 - val_accuracy: 0.6021\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import re\n",
    "from gensim.models import Word2Vec\n",
    "from keras.preprocessing.sequence import pad_sequences\n",
    "from sklearn.model_selection import train_test_split\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Embedding, Flatten, Dense\n",
    "\"\"\"\n",
    " 读取训练集并构造训练样本\n",
    "\"\"\"\n",
    "sentences = []\n",
    "\n",
    "stop = '[’!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~]+'\n",
    "for sentence in train_data['text']:\n",
    "    sentence = re.sub(stop, '', sentence)\n",
    "    sentences.append(sentence.split())\n",
    "\n",
    "\"\"\"\n",
    " 训练Word2Vec\n",
    "\"\"\"\n",
    "# 嵌入的维度\n",
    "embedding_vector_size = 10\n",
    "w2v_model = Word2Vec(\n",
    "    sentences=sentences,\n",
    "    size=8,\n",
    "    window=3,\n",
    "    workers=4)\n",
    "\n",
    "# 取得所有单词\n",
    "vocab_list = list(w2v_model.wv.vocab.keys())\n",
    "# 每个词语对应的索引\n",
    "word_index = {word: index for index, word in enumerate(vocab_list)}\n",
    "# 序列化\n",
    "def get_index(sentence):\n",
    "    global word_index\n",
    "    sequence = []\n",
    "    for word in sentence:\n",
    "        try:\n",
    "            sequence.append(word_index[word])\n",
    "        except KeyError:\n",
    "            pass\n",
    "    return sequence\n",
    "X_data = list(map(get_index, sentences))\n",
    "\n",
    "# 截长补短\n",
    "maxlen = 64\n",
    "X_pad = pad_sequences(X_data, maxlen=maxlen)\n",
    "# 取得标签\n",
    "Y = train_data['target'].values\n",
    "# 划分数据集\n",
    "X_train, X_test, Y_train, Y_test = train_test_split(\n",
    "    X_pad,\n",
    "    Y,\n",
    "    test_size=0.2,\n",
    "    random_state=42)\n",
    "\n",
    "\"\"\"\n",
    " 构建分类模型\n",
    "\"\"\"\n",
    "# 让 Keras 的 Embedding 层使用训练好的Word2Vec权重\n",
    "embedding_matrix = w2v_model.wv.vectors\n",
    "\n",
    "model = Sequential()\n",
    "model.add(Embedding(\n",
    "    input_dim=embedding_matrix.shape[0],\n",
    "    output_dim=embedding_matrix.shape[1],\n",
    "    input_length=maxlen,\n",
    "    weights=[embedding_matrix],\n",
    "    trainable=False))\n",
    "model.add(Flatten())\n",
    "# model.add(Dense(5))\n",
    "model.add(Dense(1, activation='sigmoid'))\n",
    "\n",
    "model.compile(\n",
    "    loss=\"binary_crossentropy\",\n",
    "    optimizer='adam',\n",
    "    metrics=['accuracy'])\n",
    "\n",
    "history = model.fit(\n",
    "    x=X_train,\n",
    "    y=Y_train,\n",
    "    validation_data=(X_test, Y_test),\n",
    "    batch_size=64,\n",
    "    epochs=50)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
